package com.mirabelle.juice.dao;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.mirabelle.juice.model.Author;
import com.mirabelle.juice.model.Collection;

@Repository("CollectionDao")
public class CollectionDaoImpl implements CollectionDao, Serializable {
	private static final long	serialVersionUID	= 1L;
	private transient Logger	log					= LoggerFactory.getLogger(getClass());
	
	@PersistenceUnit(unitName = "juiceUnit")
	private transient EntityManagerFactory	emf;
	
	
	@Override
	public List<Collection> getAll() {
		EntityManager em = emf.createEntityManager();
		log.debug("Envoie de la requette de recherche des collections");
		
		CriteriaBuilder b = em.getCriteriaBuilder();
		CriteriaQuery<Collection> q = b.createQuery(Collection.class);
		Root<Collection> root = q.from(Collection.class);
		q.select(root);
		TypedQuery<Collection> query = em.createQuery(q);
		q.orderBy(b.asc(root.get("modified")));
		List<Collection> r = null;
		r = query.getResultList();
		
		em.close();
		return r;
	}

	@Override
	public List<Collection> findByAuthor(Author author) {
		EntityManager em = emf.createEntityManager();
		log.debug("Envoie de la requette de recherche de la collection pour l'autheur : " + author.getMail());
		
		CriteriaBuilder b = em.getCriteriaBuilder();
		CriteriaQuery<Collection> q = b.createQuery(Collection.class);
		Root<Collection> root = q.from(Collection.class);
		q.where(b.equal(root.<Author> get("author"), author));
		
		TypedQuery<Collection> query = em.createQuery(q);
		List<Collection> r = null;
		r = query.getResultList();
		
		em.close();
		return r;
	}

	@Override
	public Collection getOne(int id) {
		EntityManager em = emf.createEntityManager();
		log.debug("Envoie de la requette de recherche de la collection pour l'identifiant : " + id);
		Collection r = em.find(Collection.class, id);
		if (null != r) {
			log.debug("Collection trouvé pour l'identifiant : " + id);
		} else {
			log.debug("Collection introuvable pour l'identifiant : " + id);
		}
		em.close();
		return r;
	}

	@Override
	public void add(Collection collection) {
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		if (null != getOne(collection.getId())) {
			log.debug("Envoie de la requette de modification de la collection pour l'identifiant : " + collection.getId());
			em.merge(collection);
		} else {
			log.debug("Envoie de la requette de création de la collection pour l'identifiant : " + collection.getId());
			em.persist(collection);
		}
		em.getTransaction().commit();
		em.close();
	}
	
	@Override
	public void remove(Collection collection) {
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		if (null != getOne(collection.getId())) {
			log.debug("Envoie de la requette de suppression de la collection pour l'identifiant : " + collection.getId());
			em.remove(em.merge(collection));
		}
		em.getTransaction().commit();
		em.close();
	}
	
	@Override
	public void save(Collection collection) {
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		if ((null != collection.getId())&&(null != getOne(collection.getId()))) {
			log.debug("Envoie de la requette de modification de la collection pour l'identifiant : " + collection.getId());
			em.merge(collection);
		} else {
			log.debug("Envoie de la requette de création de la collection pour l'identifiant : " + collection.getId());
			em.persist(collection);
		}
		em.flush();
		em.getTransaction().commit();
		em.close();
	}
}
